package com.smart.speaker.websocket;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.audio.asr.recognition.Recognition;
import com.alibaba.dashscope.audio.tts.SpeechSynthesizer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class SpeakerController extends AbstractWebSocketHandler {

    @Autowired
    @Qualifier("recognitionGenericObjectPool")
    private GenericObjectPool<Recognition> recognitionGenericObjectPool;
    @Autowired
    @Qualifier("speechSynthesizerGenericObjectPool")
    private GenericObjectPool<SpeechSynthesizer> speechSynthesizerGenericObjectPool;
    @Autowired
    private Generation generation;

    private final Map<String, SessionHandler> handlerMap;

    public SpeakerController() {
        this.handlerMap = new ConcurrentHashMap<>();
    }

    @Override
    public void afterConnectionEstablished(@NotNull WebSocketSession session) throws Exception {
        log.info("connect open");
        handlerMap.put(session.getId(), new SessionHandler(session, generation, recognitionGenericObjectPool, speechSynthesizerGenericObjectPool));
    }

    @Override
    public void handleTextMessage(@NotNull WebSocketSession session, @NotNull TextMessage message) {
        log.info("speaker message: {}", message.getPayload());
        SessionHandler handler = handlerMap.get(session.getId());
        handler.handleTextMessage(message.getPayload());
    }

    @Override
    public void handleBinaryMessage(@NotNull WebSocketSession session, @NotNull BinaryMessage message) {
        log.info("data length {}", message.getPayloadLength());
        SessionHandler handler = handlerMap.get(session.getId());
        handler.handleBinaryMessage(message.getPayload().array());
    }

    @Override
    public void handleTransportError(@NotNull WebSocketSession session, @NotNull Throwable exception) {
        log.error("connect error", exception);
    }

    @Override
    public void afterConnectionClosed(@NotNull WebSocketSession session, @NotNull CloseStatus closeStatus) {
        log.info("connect close");
        SessionHandler handler = handlerMap.remove(session.getId());
        handler.close();
    }

    @Scheduled(fixedDelay = 10000)
    public void checkAndClose() {
        try {
            for (Map.Entry<String, SessionHandler> entry : handlerMap.entrySet()) {
                SessionHandler handler = entry.getValue();
                handler.checkAndClose();
            }
        } catch (Exception e) {
            log.warn("超时关闭会话", e);
        }
    }

}
